package com.tianma315.admin.invocie.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.tianma315.admin.agent.domain.AgentDO;
import com.tianma315.admin.agent.service.AgentService;
import com.tianma315.admin.common.base.CoreServiceImpl;
import com.tianma315.admin.common.exception.MessageException;
import com.tianma315.admin.invocie.dao.InvoiceDao;
import com.tianma315.admin.invocie.dao.InvoiceProductDao;
import com.tianma315.admin.invocie.domain.Invoice;
import com.tianma315.admin.invocie.domain.InvoiceProduct;
import com.tianma315.admin.invocie.domain.InvoiceProductVO;
import com.tianma315.admin.invocie.domain.LogisticsCompanyDO;
import com.tianma315.admin.invocie.domain.dto.InvoiceDto;
import com.tianma315.admin.invocie.domain.dto.ProductForm;
import com.tianma315.admin.invocie.domain.vo.InvoiceVo;
import com.tianma315.admin.invocie.service.InvoiceService;
import com.tianma315.admin.invocie.service.LogisticsCompanyService;
import com.tianma315.admin.product.dao.ProductDao;
import com.tianma315.admin.product.domain.Product;
import com.tianma315.admin.product.domain.vo.ProductVo;
import com.tianma315.admin.product.service.ProductService;
import com.tianma315.admin.stock.dao.StockDao;
import com.tianma315.admin.stock.domain.Stock;
import com.tianma315.admin.util.CellUtil;
import com.tianma315.admin.util.HiddenSheetUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

//                   _ooOoo_
//                  o8888888o
//                  88" . "88
//                  (| -_- |)
//                  O\  =  /O
//               ____/`---'\____
//             .'  \\|     |//  `.
//            /  \\|||  :  |||//  \
//           /  _||||| -:- |||||-  \
//           |   | \\\  -  /// |   |
//           | \_|  ''\---/''  |   |
//           \  .-\__  `-`  ___/-. /
//         ___`. .'  /--.--\  `. . __
//      ."" '<  `.___\_<|>_/___.'  >'"".
//     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//     \  \ `-.   \_ __\ /__ _/   .-` /  /
//======`-.____`-.___\_____/___.-`____.-'======
//                   `=---='
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//         佛祖保佑       永无BUG

/**
 * Description
 * <p>
 * Created by zcm on 2019/5/23.
 */
@Service
@Transactional
public class InvoiceServiceImpl extends CoreServiceImpl<InvoiceDao, Invoice> implements InvoiceService {
    @Autowired
    private InvoiceProductDao invoiceProductDao;
    @Autowired
    private StockDao stockDao;
    @Autowired
    private ProductDao productDao;

    @Autowired
    private ProductService productService;

    @Autowired
    private AgentService agentService;

    @Autowired
    private LogisticsCompanyService logisticsCompanyService;
    @Autowired
    private InvoiceService invoiceService;
    @Autowired
    private InvoiceDao invoiceDao;


    @Override
    public Page<InvoiceVo> getPage(Integer pageNumber, Integer pageSize, String searchKey) {
        Page<InvoiceVo> page = new Page<>(pageNumber, pageSize);
        InvoiceVo invoiceVo = new InvoiceVo();
         List<InvoiceVo> list = baseMapper.selectPageBy(page, searchKey);
//         if (list!=null ||searchKey!=null ||searchKey.equals("")){
//             for (int i = 0; i < list.size() ; i++) {
//                 List<ProductVo> productList = list.get(i).getProducts();
//                 for (int j = 0; j < productList.size(); j++) {
//                     if (productList.get(j).getCode().indexOf(searchKey)==-1){
//                         list.remove(i);
//                     }
//                 }
//             }
//         }
        page.setRecords(list);
        return page;
    }

    @Override
    public boolean save(InvoiceDto invoice) {
        Date date = new Date();
        Invoice inv = new Invoice();
        inv.setCreatedDate(date);
        inv.setCreateBy(invoice.getCreateBy());
        if (invoice.getDeliverDate() == null){
            inv.setDeliverDate(date);
        }else{
            inv.setDeliverDate(invoice.getDeliverDate() );
        }
        inv.setTel(invoice.getTel());
        inv.setDeliverAddress(invoice.getDeliverAddress());
        inv.setAgentId(invoice.getAgentId());
        inv.setLinkman(invoice.getLinkman());
        inv.setState(InvoiceDto.STATUS_DELIVERED);
        inv.setRemark(invoice.getRemark());
        inv.setCode(invoice.getCode());
        inv.setLogisticsId(invoice.getLogisticsId());
        inv.setStatus(0);
        if (!insert(inv))
            throw new MessageException("货单创建失败");


        for (ProductForm pro : invoice.getProducts()) {

            Product product = productDao.selectById(pro.getProductId());
            if (product == null)
                throw new MessageException("产品信息获取失败");

            //计算货单总价
            long result = product.getProductPrice() * pro.getProductSize();
            if (inv.getTotalPrice() !=null){
                inv.setTotalPrice(inv.getTotalPrice() + result);
            } else{
                inv.setTotalPrice(result);
            }


            //添加产品
            InvoiceProduct invoiceProduct = new InvoiceProduct();
            invoiceProduct.setInvoice_id(inv.getInvoiceId());
            invoiceProduct.setProduct_id(pro.getProductId());
            invoiceProduct.setProductSize(pro.getProductSize());
            invoiceProduct.setCode(pro.getCode());

            if (invoiceProductDao.insert(invoiceProduct) != 1)
                throw new MessageException("产绑定失败");
            //修改产品库存
            List<Stock> stocks = stockDao.selectList(new EntityWrapper<Stock>() {{
                eq("product_id", product.getProductId());
            }});
            if (stocks == null || stocks.isEmpty()) {
                throw new MessageException(String.format("%s 产品没有库存", product.getProductName()));
            }
            Stock stock = stocks.get(0);
            if (stock.getNumber() < pro.getProductSize()) {
                throw new MessageException(String.format("%s 产品库存数量不足", product.getProductName()));
            }

            stock.setNumber(stock.getNumber() - pro.getProductSize());
            if (stockDao.updateById(stock) != 1) {
                throw new MessageException(String.format("%s 库存修改失败", product.getProductName()));
            }
        }


        if (!updateById(inv)) {
            throw new MessageException("货单更新失败");
        }

        return true;
    }

    @Override
    public InvoiceVo getInvoiceById(Integer id) {
        Invoice invoice = selectById(id);
        InvoiceVo invoiceVo = new InvoiceVo();
        BeanUtils.copyProperties(invoice,invoiceVo);
        AgentDO agentDO = agentService.getById(invoice.getAgentId());
        invoiceVo.setAgentName(agentDO.getAgentName());
        return invoiceVo;
    }

    @Override
    public boolean updateInvoiceById(InvoiceDto invoiceDto) {
        Invoice invoice = selectById(invoiceDto.getInvoiceId());
        BeanUtils.copyProperties(invoiceDto,invoice);
        Boolean result = updateById(invoice);
        return result;
    }

    @Override
    @Transactional
    public boolean deleteInvoiceById(Long id) {
        Invoice invoice = invoiceService.getInvoiceById(id.intValue());
        invoice.setStatus(1);
        invoice.setInvoiceId(id);
        List<InvoiceProductVO> invoiceProducts = invoiceProductDao.getInvoiceProduct(id.intValue());

        Boolean result = updateById(invoice);
        for (InvoiceProductVO ip: invoiceProducts) {
            List<Stock> stocks = stockDao.selectList(new EntityWrapper<Stock>() {{
                eq("product_id", ip.getProductId());
            }});
            Stock stock = stocks.get(0);
            stock.setNumber(stock.getNumber()+ip.getProductSize());
            stockDao.updateById(stock);
        }
        return result;
    }

    @Override
    public HSSFWorkbook exportInvoice() {
        String[] title = {"出库日期","经销商","产品名称","数量","批号","物流公司"};
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet("出库订单模板");

//        sheet.addMergedRegion(new CellRangeAddress(0,0,0,8));//第一行第一列开始，跨8列
        HSSFRow titleRow = sheet.createRow(0);//第0行

        //标题样式
        HSSFCellStyle titleStyle = wb.createCellStyle();
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        HSSFFont font = wb.createFont();
        font.setFontHeightInPoints((short)18);
        titleStyle.setFont(font);

        //生成标题
        HSSFCell titleCell = titleRow.createCell(0);
        titleCell.setCellValue("出库订单模板（红色标识列为必填）");
        titleCell.setCellStyle(titleStyle);

        //红色字体
        HSSFCellStyle redStyle = wb.createCellStyle();
        redStyle.setAlignment(HorizontalAlignment.CENTER);
        HSSFFont redFont = wb.createFont();
        redFont.setBold(true);
        redFont.setColor(Font.COLOR_RED);
        redStyle.setFont(redFont);

        //默认字体样式
        HSSFCellStyle defaultStyle = wb.createCellStyle();
        defaultStyle.setAlignment(HorizontalAlignment.CENTER);
        HSSFFont defaultFont = wb.createFont();
        defaultFont.setBold(true);
        defaultStyle.setFont(defaultFont);

        //声明列对象
        HSSFCell cell = null;
        //创建表头
        HSSFRow headRow = sheet.createRow(1);
        for(int i=0; i<title.length; i++){
            //下标小于7是必填列
//            if (i < 7){
            cell = headRow.createCell(i);
            cell.setCellValue(title[i]);
            cell.setCellStyle(redStyle);
//            }else{
//                cell = headRow.createCell(i);
//                cell.setCellValue(title[i]);
//                cell.setCellStyle(defaultStyle);
//            }
        }

        List<AgentDO> agentDOS = agentService.getAgentList();
        List<String> agentList = agentDOS.stream().map(item -> item.getAgentName()).collect(Collectors.toList());
        String[] agentNameArr = agentList.toArray(new String[agentList.size()]);

        String agentHiddenSheet = "agentHidden";
        Integer agentCellNum = 1;
        Integer agentStartRow = 2; // 开始行
        Integer agentEndRow = 10000; // 结束行
        HiddenSheetUtil.initHiddenSheet(agentHiddenSheet,wb,agentCellNum,agentStartRow,agentEndRow,agentNameArr);
        //设置设备类型为下拉框选项
        DVConstraint agentConstraint = DVConstraint.createFormulaListConstraint(agentHiddenSheet);
        // 设置数据有效性加载在哪个单元格上,四个参数分别是：起始行、终止行、起始列、终止列
        CellRangeAddressList agentRegions = new CellRangeAddressList(agentStartRow,
                agentEndRow, agentCellNum, agentCellNum);
        HSSFDataValidation agentData = new HSSFDataValidation(
                agentRegions, agentConstraint);
        sheet.addValidationData(agentData);
//        //设置设备类型为下拉框选项
//        DVConstraint constraint = DVConstraint.createExplicitListConstraint(agentNameArr);
//        // 设置数据有效性加载在哪个单元格上,四个参数分别是：起始行、终止行、起始列、终止列
//        CellRangeAddressList regions = new CellRangeAddressList(2,
//                10000, 1, 1);
//        HSSFDataValidation materialData = new HSSFDataValidation(
//                regions, constraint);
        wb.setSheetHidden(wb.getSheetIndex(agentHiddenSheet), true);

        List<Product> productS = productService.getAll();
        List<String> productList = productS.stream().map(item -> item.getProductName()).collect(Collectors.toList());
        String[] productNameArr = productList.toArray(new String[productList.size()]);

        String productHiddenSheet = "productHidden";
        Integer productCellNum = 2;
        Integer productStartRow = 2; // 开始行
        Integer productEndRow = 10000; // 结束行
        HiddenSheetUtil.initHiddenSheet(productHiddenSheet,wb,productCellNum,productStartRow,productEndRow,productNameArr);
        //设置设备类型为下拉框选项
        DVConstraint productConstraint = DVConstraint.createFormulaListConstraint(productHiddenSheet);
        // 设置数据有效性加载在哪个单元格上,四个参数分别是：起始行、终止行、起始列、终止列
        CellRangeAddressList productRegions = new CellRangeAddressList(productStartRow,
                productEndRow, productCellNum, productCellNum);
        HSSFDataValidation productData = new HSSFDataValidation(
                productRegions, productConstraint);
        sheet.addValidationData(productData);
        wb.setSheetHidden(wb.getSheetIndex(productHiddenSheet), true);


        List<LogisticsCompanyDO> logisticsCompanyDOS = logisticsCompanyService.getAll();
        List<String> logisticsCompanyDOList = logisticsCompanyDOS.stream().map(item -> item.getLogName()).collect(Collectors.toList());
        String[] logisticsCompanyNameArr = logisticsCompanyDOList.toArray(new String[logisticsCompanyDOList.size()]);


        String logisticsHiddenSheet = "logisticsHidden";
        Integer logisticsCellNum = 5;
        Integer logisticsStartRow = 2; // 开始行
        Integer logisticsEndRow = 10000; // 结束行
        HiddenSheetUtil.initHiddenSheet(logisticsHiddenSheet,wb,logisticsCellNum,logisticsStartRow
                ,logisticsEndRow,logisticsCompanyNameArr);
        //设置设备类型为下拉框选项
        DVConstraint logisticsConstraint = DVConstraint.createFormulaListConstraint(
                logisticsHiddenSheet);
        // 设置数据有效性加载在哪个单元格上,四个参数分别是：起始行、终止行、起始列、终止列
        CellRangeAddressList logisticsRegions = new CellRangeAddressList(logisticsStartRow,
                logisticsEndRow, logisticsCellNum, logisticsCellNum);
        HSSFDataValidation logisticsData = new HSSFDataValidation(
                logisticsRegions, logisticsConstraint);

        //设置设备类型为下拉框选项
//        DVConstraint constraint2 = DVConstraint.createExplicitListConstraint(logisticsCompanyNameArr);
        // 设置数据有效性加载在哪个单元格上,四个参数分别是：起始行、终止行、起始列、终止列
//        CellRangeAddressList regions2 = new CellRangeAddressList(2,
//                10000, 5, 5);
//        HSSFDataValidation materialData2 = new HSSFDataValidation(
//                regions2, constraint2);
        sheet.addValidationData(logisticsData);
        wb.setSheetHidden(wb.getSheetIndex(logisticsHiddenSheet), true);
        return wb;
    }

    @Override
    @Transactional
    public void importInvoice(MultipartFile file, Long userId) {
        Boolean flag = CellUtil.isExcel(file.getOriginalFilename());
        if (!flag){
            throw new MessageException("只支持Excel文件");
        }

        List<Product> productList = productService.getAll();
        List<AgentDO> agentDOList = agentService.getAgentList();
        List<LogisticsCompanyDO> logisticsCompanyDOList = logisticsCompanyService.getAll();
        try {
            HSSFWorkbook wb = new HSSFWorkbook(file.getInputStream());
            Sheet sheet = wb.getSheetAt(0);
            int rowNum = sheet.getLastRowNum(); //返回行数下标 从0开始

            InvoiceDto oldInvoiceDto = new InvoiceDto();

            InvoiceDto oldInvoiceDto2 = new InvoiceDto();

            List<ProductForm> productForms = new ArrayList<>();

            oldInvoiceDto.setProducts(productForms);
            List<InvoiceDto> invoiceDtoList = new ArrayList<>();
            //前2行都不是内容，所以从2开始
            for (int i = 2; i <= rowNum; i++) {
                System.out.println("第"+i+"条");
                Row row = sheet.getRow(i);
                short num = row.getLastCellNum();
                InvoiceDto invoiceDto = new InvoiceDto();
                invoiceDto.setStatus(Invoice.STATUS_DELIVERED);
                invoiceDto.setCreateBy(userId);
                invoiceDto.setCreatedDate(Calendar.getInstance().getTime());

                ProductForm productForm = new ProductForm();
                //设置出库时间
                Cell deliverDate = row.getCell(0);
                if (deliverDate!=null){
//                    deliverDate.setCellType(CellType.NUMERIC);
                    if (deliverDate.getDateCellValue()!=null){
                        oldInvoiceDto.setDeliverDate(deliverDate.getDateCellValue());
                        invoiceDto.setDeliverDate(deliverDate.getDateCellValue());
                    }

                }
                //设置经销商
                Cell agentCell = row.getCell(1);
                //如果为空说明是同一个订单
                if (CellUtil.isCellEmpty(agentCell)){
//                    throw new MessageException("经销商不能为空");
                }else{
                    //设置经销商信息
                    List<AgentDO> agentFilterResult = agentDOList.stream()
                            .filter(item -> item.getAgentName().equals(agentCell.getStringCellValue()))
                            .collect(Collectors.toList());
                    if (CollectionUtils.isEmpty(agentFilterResult)){
                        throw new MessageException(agentCell.getStringCellValue()+"未找到");
                    }else{
                        AgentDO agentDO = agentFilterResult.get(0);
                        invoiceDto.setAgentId(agentDO.getAgentId());
                        invoiceDto.setTel(agentDO.getTel());
                        invoiceDto.setDeliverAddress(agentDO.getAddress());
                        invoiceDto.setLinkman(agentDO.getLinkman());
                    }
                }

                //设置产品id
                Cell productCell = row.getCell(2);
                if (CellUtil.isCellEmpty(productCell)){
                    throw new MessageException("产品名称不能为空");
                }
                List<Product> productFilterResult = productList.stream()
                        .filter(item -> item.getProductName().equals(productCell.getStringCellValue()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(productFilterResult)){
                    throw new MessageException(productCell.getStringCellValue()+"未找到");
                }else{
                    productForm.setProductId(productFilterResult.get(0).getProductId());
                }

                //设置数量
                Cell numberCell = row.getCell(3);
                Integer number = 0;
                if (!CellUtil.isCellEmpty(numberCell)){
                    number = Integer.parseInt(numberCell.getStringCellValue());
                }else{
                    throw new MessageException("数量不能为空");
                }
                productForm.setProductSize(number);

                //设置批次
                Cell codeNameCell = row.getCell(4);
                if (codeNameCell != null ){
                    codeNameCell.setCellType(CellType.STRING);
                    productForm.setCode(codeNameCell.getStringCellValue());
                }else{
                    throw new MessageException("批次不能为空");
                }

                productForms.add(productForm);

                //设置快递公司
                Cell logisticsCell = row.getCell(5);
                if (CellUtil.isCellEmpty(logisticsCell)){
                    throw new MessageException("快递公司不能为空");
                }
                List<LogisticsCompanyDO> logisticsCompanyFilterResult = logisticsCompanyDOList.stream()
                        .filter(item -> item.getLogName().equals(logisticsCell.getStringCellValue()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(logisticsCompanyFilterResult)){
                    throw new MessageException(logisticsCell.getStringCellValue()+"未找到");
                }else{
                    invoiceDto.setLogisticsId(logisticsCompanyFilterResult.get(0).getId().intValue());
//                    oldInvoiceDto.setLogisticsId(logisticsCompanyFilterResult.get(0).getId().intValue());
                }



                if (i ==2 && rowNum != 2){
//                    System.out.println("false");
                    BeanUtils.copyProperties(invoiceDto,oldInvoiceDto);
                }else if(i ==2 && rowNum == 2){//如果rowNum为2时，说明只有一条记录，直接插入即可
                    invoiceDto.setProducts(productForms);
                    save(invoiceDto);
                }else if(invoiceDto.getDeliverDate()==null && i != rowNum){//这不是最后一条记录
                    System.out.println("空置");
                }else if(invoiceDto.getDeliverDate()==null && i == rowNum){//插入最后一条记录
//                    productForms.remove(productForms.size()-1);
                    oldInvoiceDto.setProducts(productForms);
                    save(oldInvoiceDto);
                }else{
                    productForms.remove(productForms.size()-1);//把旧的产品删除
                    oldInvoiceDto.setProducts(productForms);
                    save(oldInvoiceDto);
                    BeanUtils.copyProperties(invoiceDto,oldInvoiceDto);
                    productForms.clear();
                    productForms.add(productForm);
                    if (i == rowNum){
                        invoiceDto.setProducts(productForms);
                        System.out.println("insert last");
                        save(invoiceDto);
                    }
                }
//                save(warehousingRecord);
            }
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    @Override
    public List<InvoiceVo> getInvoiceByProductId(Long productId, String batch) {
        List<InvoiceVo> result = invoiceDao.getInvoiceByProductId(productId,batch);
        return result;
    }
}
